package es.tikitaka.actions.competicion;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.faces.context.FacesContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import net.sf.jooreports.templates.DocumentTemplateException;
import net.sf.jooreports.templates.ZippedDocumentTemplate;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

import com.artofsolving.jodconverter.DefaultDocumentFormatRegistry;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.DocumentFormat;
import com.artofsolving.jodconverter.DocumentFormatRegistry;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;

import es.tikitaka.domain.Amonestacion;
import es.tikitaka.domain.Gol;
import es.tikitaka.domain.Partido;
import es.tikitaka.domain.equipo.SegEquipo;
import es.tikitaka.domain.jugador.SegJugador;
import es.tikitaka.domain.liga.PartidoL;
import es.tikitaka.domain.playoffs.PartidoPO;

/**
 * 
 * @author Saúl Domínguez
 * @since 2010
 * @category PFC
 */

@Name("exportPartido")
@Scope(ScopeType.CONVERSATION)
public class ExportarFichaPartidoAction {

	private ZippedDocumentTemplate z;
	private String temporada;
	private String tipoPartido;
	private String numJornada;
	private String fechaJornada;
	private String estado;
	private String local;
	private String visitante;
	private String golesL;
	private String golesV;
	private StringBuffer colegiado;
	private StringBuffer goles;
	private StringBuffer tarjetas;

	private List<SegJugador> locales;
	private List<SegJugador> visitantes;

	/**
	 * Constructor por defecto
	 */
	public ExportarFichaPartidoAction() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * Método para generar un pdf con los datos del jugador
	 * 
	 * @param jugador
	 *            Jugador para el que se genera el pdf
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public int exportFichaPartidoPdf(Partido partido) {

		Map map = new HashMap();

		// iniciamos las variables
		temporada = new String();
		tipoPartido = new String();
		numJornada = new String();
		fechaJornada = new String();
		estado = new String();
		local = new String();
		visitante = new String();
		golesL = new String();
		golesV = new String();
		colegiado = new StringBuffer();
		goles = new StringBuffer();
		tarjetas = new StringBuffer();

		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

		if (partido instanceof PartidoL) {
			tipoPartido = "LIGA REGULAR";
			PartidoL part = (PartidoL) partido;
			numJornada = Integer.valueOf(part.getJornada().getNumJor())
					.toString();
			fechaJornada = sdf.format(part.getJornada().getFecha()).toString();
		} else if (partido instanceof PartidoPO) {
			tipoPartido = "PLAYOFFS";
			PartidoPO part = (PartidoPO) partido;
		}

		temporada = Integer.valueOf(
				partido.getColegiado().getPartColegiado().getTemporada()
						.getAnio().getAnio()).toString();
		estado = "Finalizado";
		colegiado.append(partido.getColegiado().getPartColegiado()
				.getColegiado().getApellidos());
		colegiado.append(", ");
		colegiado.append(partido.getColegiado().getPartColegiado()
				.getColegiado().getNombre());
		local = partido.getLocal();
		visitante = partido.getVisitante();
		golesL = Integer.valueOf(partido.getGolesL()).toString();
		golesV = Integer.valueOf(partido.getGolesV()).toString();
		goles = golesPartido(partido);
		tarjetas = tarjetasPartido(partido);

		// Añadimos los datos al map
		map.put("temporada", temporada);
		map.put("tipoPartido", tipoPartido);
		map.put("numJornada", numJornada);
		map.put("fechaJornada", fechaJornada);
		map.put("estado", estado);
		map.put("local", local);
		map.put("visitante", visitante);
		map.put("golesL", golesL);
		map.put("golesV", golesV);
		map.put("colegiado", colegiado);
		map.put("goles", goles);
		map.put("tarjetas", tarjetas);

		// Cogemos la plantilla odt
		URL uri = this.getClass().getClassLoader().getResource(
				"plantillas/acta.odt");
		File file = null;

		try {
			file = new File(uri.toURI());
		} catch (URISyntaxException e1) {
			e1.printStackTrace();
		}

		try {
			// connect to an OpenOffice.org instance running on port 8100
			String host = ResourceBundle.getBundle("openoffice").getString(
					"host");
			int port = Integer.parseInt(ResourceBundle.getBundle("openoffice")
					.getString("port"));
			OpenOfficeConnection connection = new SocketOpenOfficeConnection(
					host, port);
			connection.connect();

			ByteArrayOutputStream out = new ByteArrayOutputStream();

			z = new ZippedDocumentTemplate(file);

			z.createDocument(map, out);
			byte[] b = out.toByteArray();

			// convert
			DocumentConverter converter = new StreamOpenOfficeDocumentConverter(
					connection);

			DocumentFormatRegistry registry = new DefaultDocumentFormatRegistry();
			DocumentFormat odt = registry.getFormatByFileExtension("odt");
			DocumentFormat pdf = registry.getFormatByFileExtension("pdf");

			ByteArrayOutputStream outpdf = new ByteArrayOutputStream();

			ByteArrayInputStream in = new ByteArrayInputStream(b);
			converter.convert(in, odt, outpdf, pdf);
			byte[] bpdf = outpdf.toByteArray();

			connection.disconnect();

			FacesContext faces = FacesContext.getCurrentInstance();
			HttpServletResponse response = (HttpServletResponse) faces
					.getExternalContext().getResponse();

			String pdfname = "\"Acta.pdf\"";
			response.setContentType("application/pdf");
			response.setContentLength(bpdf.length);
			response.setHeader("Content-disposition", "attachment; filename="
					+ pdfname);
			ServletOutputStream desc = response.getOutputStream();
			desc.write(bpdf);

			faces.responseComplete();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("No se puede abrir el archivo");
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("Error de I/O");
			e.printStackTrace();
		} catch (DocumentTemplateException e) {
			// TODO Auto-generated catch block
			System.out.println("Error en la plantilla");
			e.printStackTrace();
		}

		return 0;

	}

	/**
	 * Método para obtener el conjunto de goles del partido
	 * 
	 * @return
	 */
	public StringBuffer golesPartido(Partido partido) {
		int golesL = 0;
		int golesV = 0;
		List<Gol> golesPartido = new ArrayList<Gol>();
		golesPartido.addAll(partido.getM_goles());
		Collections.sort(golesPartido);
		obtenerLocalVisitante(partido);
		for (Gol g : golesPartido) {
			if (locales.contains(g.getJugador())) {
				golesL++;
			} else {
				golesV++;
			}
			// rellenamos incidencias
			goles.append(golesL);
			goles.append("-");
			goles.append(golesV);
			goles.append(": ");
			goles.append(g.getPeriodo());
			goles.append("ª parte, ");
			goles.append("min ");
			goles.append(g.getMinuto());
			goles.append(". ");
			goles.append(g.getJugador().getPartJugador().getJugador()
					.getNombre());
			if (g.getTipoGol().getTipo().equals("Gol penalty")) {
				goles.append("(p.)");
			}
			goles.append("; ");
		}
		return goles;
	}

	/**
	 * Método para obtener el conjunto de tarjetas mostradas en el partido
	 * 
	 * @param partido
	 * @return
	 */
	public StringBuffer tarjetasPartido(Partido partido) {

		List<Amonestacion> amonestacionesPartido = new ArrayList<Amonestacion>();
		amonestacionesPartido.addAll(partido.getM_amonestaciones());
		Collections.sort(amonestacionesPartido);
		for (Amonestacion a : amonestacionesPartido) {
			// rellenamos incidencias
			if (a.getTipo() != null) {
				tarjetas.append(a.getPeriodo());
				tarjetas.append("ª parte, ");
				tarjetas.append("min ");
				tarjetas.append(a.getMin());
				tarjetas.append(". ");
				tarjetas.append(a.getTipo().getTipo());
				tarjetas.append(" a ");
				tarjetas.append(a.getJugador().getPartJugador().getJugador()
						.getNombre());
				tarjetas.append("; ");
			}
		}
		return tarjetas;
	}

	private void obtenerLocalVisitante(Partido par) {
		if (par != null) {
			List<SegEquipo> equipos = new ArrayList<SegEquipo>();
			equipos.addAll(par.getM_equipos());
			for (SegEquipo eq : equipos) {
				if (eq.getPartEquipo().getEquipo().getNombre().equals(
						par.getLocal())) {
					locales = new ArrayList<SegJugador>();
					locales.addAll(eq.getM_jugadores());
					Collections.sort(locales);
				} else {
					visitantes = new ArrayList<SegJugador>();
					visitantes.addAll(eq.getM_jugadores());
					Collections.sort(visitantes);
				}
			}
		}
	}

	/*
	 * getters and setters
	 */

	/**
	 * 
	 * @return
	 */
	public String getTemporada() {
		return temporada;
	}

	/**
	 * 
	 * @param temporada
	 */
	public void setTemporada(String temporada) {
		this.temporada = temporada;
	}

	/**
	 * 
	 * @return
	 */
	public String getTipoPartido() {
		return tipoPartido;
	}

	/**
	 * 
	 * @param tipoPartido
	 */
	public void setTipoPartido(String tipoPartido) {
		this.tipoPartido = tipoPartido;
	}

	/**
	 * 
	 * @return
	 */
	public String getNumJornada() {
		return numJornada;
	}

	/**
	 * 
	 * @param numJornada
	 */
	public void setNumJornada(String numJornada) {
		this.numJornada = numJornada;
	}

	/**
	 * 
	 * @return
	 */
	public String getFechaJornada() {
		return fechaJornada;
	}

	/**
	 * 
	 * @param fechaJornada
	 */
	public void setFechaJornada(String fechaJornada) {
		this.fechaJornada = fechaJornada;
	}

	/**
	 * 
	 * @return
	 */
	public String getEstado() {
		return estado;
	}

	/**
	 * 
	 * @param estado
	 */
	public void setEstado(String estado) {
		this.estado = estado;
	}

	/**
	 * 
	 * @return
	 */
	public String getLocal() {
		return local;
	}

	/**
	 * 
	 * @param local
	 */
	public void setLocal(String local) {
		this.local = local;
	}

	/**
	 * 
	 * @return
	 */
	public String getVisitante() {
		return visitante;
	}

	/**
	 * 
	 * @param visitante
	 */
	public void setVisitante(String visitante) {
		this.visitante = visitante;
	}

	/**
	 * 
	 * @return
	 */
	public String getGolesL() {
		return golesL;
	}

	/**
	 * 
	 * @param golesL
	 */
	public void setGolesL(String golesL) {
		this.golesL = golesL;
	}

	/**
	 * 
	 * @return
	 */
	public String getGolesV() {
		return golesV;
	}

	/**
	 * 
	 * @param golesV
	 */
	public void setGolesV(String golesV) {
		this.golesV = golesV;
	}

	/**
	 * 
	 * @return
	 */
	public StringBuffer getColegiado() {
		return colegiado;
	}

	/**
	 * 
	 * @param colegiado
	 */
	public void setColegiado(StringBuffer colegiado) {
		this.colegiado = colegiado;
	}

	/**
	 * 
	 * @return
	 */
	public StringBuffer getGoles() {
		return goles;
	}

	/**
	 * 
	 * @param goles
	 */
	public void setGoles(StringBuffer goles) {
		this.goles = goles;
	}

	/**
	 * 
	 * @return
	 */
	public StringBuffer getTarjetas() {
		return tarjetas;
	}

	/**
	 * 
	 * @param tarjetas
	 */
	public void setTarjetas(StringBuffer tarjetas) {
		this.tarjetas = tarjetas;
	}

	/**
	 * 
	 * @return
	 */
	public List<SegJugador> getLocales() {
		return locales;
	}

	/**
	 * 
	 * @param locales
	 */
	public void setLocales(List<SegJugador> locales) {
		this.locales = locales;
	}

	/**
	 * 
	 * @return
	 */
	public List<SegJugador> getVisitantes() {
		return visitantes;
	}

	/**
	 * 
	 * @param visitantes
	 */
	public void setVisitantes(List<SegJugador> visitantes) {
		this.visitantes = visitantes;
	}
}
